from sqlalchemy import Column, Integer, String, DateTime, Float, ForeignKey, func
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import relationship
from database import Base


class PerfMessages(Base):
    __tablename__ = "perf_script"
    __table_args__ = {'comment': 'Locust 脚本表'}

    id = Column(Integer, primary_key=True, index=True, comment="主键ID")
    user_id = Column(Integer, index=True, comment="所属用户ID")
    filename = Column(String(100), nullable=False, comment="脚本文件名")
    remarks = Column(String(255), nullable=True, comment="脚本备注")
    created_at = Column(DateTime, default=func.now(), nullable=False, comment="创建时间")

    # ORM 反向关系：一个脚本可以关联多个压测任务
    perf_script_tasks = relationship("PerfTask", back_populates="script", cascade="all, delete-orphan")

    def __repr__(self):
        return f"<PerfMessages(user_id={self.user_id}, filename='{self.filename}')>"


class PerfTask(Base):
    __tablename__ = "perf_task"
    __table_args__ = {'comment': 'Locust 压测任务记录表'}

    id = Column(Integer, primary_key=True, index=True, comment="主键ID")
    task_id = Column(String(64), index=True, unique=True, nullable=False, comment="任务唯一标识UUID")
    user_id = Column(Integer, nullable=False, comment="创建任务的用户ID")

    # 外键：关联脚本表 perf_script.id
    script_id = Column(Integer, ForeignKey("perf_script.id"), nullable=False, comment="关联的脚本ID")

    filename = Column(String(255), nullable=False, comment="上传的Locust脚本文件名（冗余字段，便于展示）")
    start_time = Column(DateTime, default=func.now(), comment="压测任务开始时间")
    end_time = Column(DateTime, comment="压测任务结束时间")
    status = Column(String(32), comment="任务状态（running/finished/failed）")
    users = Column(Integer, comment="模拟的用户数量")
    spawn_rate = Column(Integer, comment="每秒启动的用户数")
    run_time = Column(String(20), comment="压测时长，例如：'1m'、'30s'")
    host = Column(String(255), comment="被压测的主机地址")
    csv_report_path = Column(String(255), comment="压测报告CSV文件路径")
    log_file_path = Column(String(255), comment="压测日志文件路径")
    path = Column(String(255), comment="日志文件路径")
    # ORM 正向关系
    script = relationship("PerfMessages", back_populates="perf_script_tasks")

    task_stats = relationship("PerfTaskStatsJson", back_populates="perf_tasks", cascade="all, delete-orphan")
    csv_failures = relationship("PerfTaskStatsCsv", back_populates="perf_tasks", cascade="all, delete-orphan")

    def __repr__(self):
        return f"<PerfTask(task_id='{self.task_id}', user_id={self.user_id}, status='{self.status}')>"


class PerfTaskStatsJson(Base):
    __tablename__ = "perf_task_stats_json"
    __table_args__ = {'comment': '每个接口的json压测统计数据'}

    id = Column(Integer, primary_key=True, comment="主键ID")
    task_id = Column(String(64), ForeignKey("perf_task.task_id"), nullable=False, index=True,
                     comment="对应的压测任务ID")
    name = Column(String(255), nullable=False, comment="接口路径，例如 /api/user/v1/login")
    method = Column(String(10), nullable=False, comment="请求方法，例如 GET、POST")
    num_requests = Column(Integer, comment="请求总数")
    num_failures = Column(Integer, comment="失败请求总数")
    total_response_time = Column(Float, comment="总响应时间（单位：毫秒）")
    min_response_time = Column(Float, comment="最小响应时间（单位：毫秒）")
    max_response_time = Column(Float, comment="最大响应时间（单位：毫秒）")
    avg_response_time = Column(Float, comment="平均响应时间（单位：毫秒）")
    total_content_length = Column(Integer, comment="响应内容总字节数")
    response_times = Column(LONGTEXT, comment="响应时间分布，格式为 JSON 字符串，键为响应时间区间，值为次数")
    num_reqs_per_sec = Column(LONGTEXT, comment="每秒请求数，格式为 JSON 字符串，键为时间戳，值为请求数")
    num_fail_per_sec = Column(LONGTEXT, comment="每秒失败请求数，格式为 JSON 字符串，键为时间戳，值为失败数")
    tps = Column(Float, comment="每秒事务数（吞吐率）")

    perf_tasks = relationship("PerfTask", back_populates="task_stats")


class PerfTaskStatsCsv(Base):
    __tablename__ = "perf_task_failures_csv"
    __table_args__ = {'comment': '每个接口的failures.csv压测统计数据'}

    id = Column(Integer, primary_key=True, comment="主键ID")
    task_id = Column(String(64), ForeignKey("perf_task.task_id"), nullable=False, index=True,
                     comment="对应的压测任务ID")

    name = Column(String(255), nullable=True, comment="接口路径，例如 /api/user/v1/login")
    method = Column(String(10), nullable=True, comment="请求方法，例如 GET、POST")
    error = Column(LONGTEXT, nullable=True, comment="错误信息")
    occurrences = Column(Integer, nullable=True, comment="该异常类型在压测过程中出现的总次数")
    perf_tasks = relationship("PerfTask", back_populates="csv_failures")
